package com.tjbank.cssys.service.impl;

import com.tjbank.cssys.api.RelationAddService;
import com.tjbank.cssys.api.RelationIDService;
import com.tjbank.cssys.api.RoleService;
import com.tjbank.cssys.dto.*;
import com.tjbank.cssys.entityext.DataPermParam;
import com.tjbank.cssys.framework.base.enums.YesOrNoEnum;
import com.tjbank.cssys.framework.base.exception.ServiceException;
import com.tjbank.cssys.framework.base.util.GeneratIDUtil;
import com.tjbank.cssys.mapperext.PermissionMapper;
import com.tjbank.cssys.mapperext.UserMapper;
import com.tjbank.cssys.mybatis.IamRelationshipDao;
import com.tjbank.cssys.mybatis.IamRoleDao;
import com.tjbank.cssys.mybatis.entity.IamRelationship;
import com.tjbank.cssys.mybatis.entity.IamRole;
import com.tjbank.cssys.mybatis.entity.IamRoleKey;
import com.tjbank.cssys.mybatis.mapper.IamRelationshipMapper;
import com.tjbank.cssys.mybatis.mapper.IamRoleMapper;
import com.tjbank.cssys.mybatis.sqlbuilder.IamRelationshipSqlBuilder;
import com.tjbank.cssys.mybatis.sqlbuilder.IamRoleSqlBuilder;
import com.tjbank.cssys.service.convert.OrganConvert;
import com.tjbank.cssys.service.convert.PermissionConvert;
import com.tjbank.cssys.service.convert.RoleConvert;
import com.tjbank.cssys.service.convert.UserConvert;
import com.tjbank.cssys.service.enums.RelaCodeEnum;
import com.tjbank.cssys.service.util.Const;
import com.tjbank.cssys.service.util.ForestNodeMerger;
import com.tjbank.cssys.service.util.PermissionUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 角色
 * 
 * Package : com.tansun.magicube.iam.service.impl
 * 
 * @author -- lijiangtao 2020年5月5日 下午4:15:05
 *
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private IamRoleDao roleDao;

    @Autowired
    private IamRelationshipDao relationshipDao;

    /** 关联关系ID **/
    @Autowired
    private RelationIDService relationIDService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RelationAddService relationAddService;

    /** 权限 **/
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private IamRelationshipMapper iamRelationshipMapper;
    @Autowired
    private IamRoleMapper iamRoleMapper;
    @Value("${orginGrade}")
    private String orginGrade;

    /**
     * 新增
     * 
     * @param roleDTO
     * @return
     * @author -- lijiangtao 2020年5月9日 下午4:04:21
     */
    @Override
    @Transactional
    public Integer addRole(RoleDTO roleDTO) {
        IamRole entity = RoleConvert.INSTANCE.dtoToEntity(roleDTO);
        entity.setId(GeneratIDUtil.getUUId());
        entity.setState(YesOrNoEnum.YES.getCode());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        return roleDao.insert(entity);
    }

    /**
     * 根据租户Code分页查询角色信息
     * 
     * @param roleDTO
     * @param pageable
     * @return
     * @author -- lijiangtao 2020年5月7日 下午3:27:25
     */
    @Override
    @SuppressWarnings("all")
    public Page<RoleDTO> queryRoleByTenantCode(RoleDTO roleDTO, Pageable pageable) {
        IamRoleSqlBuilder sqlBuilder = this.setSqlBuilderByTenantCode(roleDTO, pageable);
        return new PageImpl(RoleConvert.INSTANCE.entitiesToDtoList(roleDao.selectListBySqlBuilder(sqlBuilder)), pageable, roleDao.countBySqlBuilder(sqlBuilder));
    }

    /**
     * setSqlBuilder
     * 
     * @param roleDTO
     * @param pageable
     * @return
     * @author -- lijiangtao 2020年7月18日 下午3:35:47
     */
    private IamRoleSqlBuilder setSqlBuilderByTenantCode(RoleDTO roleDTO, Pageable pageable) {
        if (StringUtils.isEmpty(roleDTO.getTenantCode())) {
            throw new ServiceException("tenantCode:租户代码不能为空");
        }
        IamRoleSqlBuilder sqlBuilder = new IamRoleSqlBuilder();
        sqlBuilder.setPageSize(pageable.getPageSize());
        sqlBuilder.setIndexNo((int) pageable.getOffset());
        if (StringUtils.isNotBlank(roleDTO.getRoleName())) {
            sqlBuilder.andRoleNameLikeBoth(roleDTO.getRoleName());
        }
        sqlBuilder.andTenantCodeEqualTo(roleDTO.getTenantCode()).andIsDeletedEqualTo(YesOrNoEnum.NO.getCode()).orderByUpdateTime(true).setAutoFilterNull(true);
        return sqlBuilder;
    }

    /**
     * 删除
     * 
     * @param roleId
     * @return
     * @author -- lijiangtao 2020年5月9日 下午4:04:23
     */
    @Override
    @Transactional
    public Integer deleteRole(String roleId) {
        this.checkRoleId(roleId);
        if (!relationIDService.queryUserIdListByRoleId(roleId).isEmpty()) {
            throw new ServiceException("该角色下存在用户!");
        }
        relationAddService.deletePermissionByRoleId(roleId);
        return roleDao.deleteByPrimaryKey(new IamRoleKey(roleId));
    }

    /**
     * 校验角色ID
     * 
     * @param roleId
     * @author -- lijiangtao 2020年6月20日 下午3:55:10
     */
    private void checkRoleId(String roleId) {
        if (StringUtils.isBlank(roleId)) {
            throw new ServiceException("查询角色ID为空");
        }
    }

    /**
     * 更新
     * 
     * @param roleDTO
     * @return
     * @author -- lijiangtao 2020年5月9日 下午4:04:26
     */
    @Override
    @Transactional
    public Integer updateRole(RoleDTO roleDTO) {
        this.checkRoleId(roleDTO.getId());
        IamRole entity = RoleConvert.INSTANCE.dtoToEntity(roleDTO);
        entity.setUpdateTime(new Date());
        IamRoleSqlBuilder sqlBuilder = new IamRoleSqlBuilder();
        sqlBuilder.andIdEqualTo(entity.getId());
        return roleDao.updateBySqlBuilder(entity, sqlBuilder);
    }

    /**
     * 根据角色ID查询
     * 
     * @param roleId
     * @return
     * @author -- lijiangtao 2020年6月20日 下午4:03:48
     */
    @Override
    public RoleDetailsDTO queryRole(String roleId) {
        this.checkRoleId(roleId);
        RoleDetailsDTO roleDetailsDTO = new RoleDetailsDTO();
        // 根据角色ID查询角色信息
        roleDetailsDTO.setRoleDTO(RoleConvert.INSTANCE.entityToDto(roleDao.selectByPrimaryKey(new IamRoleKey(roleId))));
        // 根据角色ID查询用户信息
        roleDetailsDTO.setUserList(this.queryUserListByRoleId(roleId));
        // 根据角色ID查询菜单权限
        roleDetailsDTO.setMenuPerm(this.queryMenuPermission(roleId));
        // 根据角色ID查询接口权限
        roleDetailsDTO.setApiPerm(this.queryAPIPermission(roleId));
        // 根据角色ID查询数据权限
        roleDetailsDTO.setDataPerm(this.queryDataPermission(roleId));
        return roleDetailsDTO;
    }

    /**
     * 根据角色ID查询用户信息集合
     * 
     * @param roleId
     * @return
     * @author -- lijiangtao 2020年5月9日 上午10:29:34
     */
    private List<UserDTO> queryUserListByRoleId(String roleId) {
        List<String> userIdList = relationIDService.queryUserIdListByRoleId(roleId);
        if (userIdList.isEmpty()) {
            return null;
        }
        return UserConvert.INSTANCE.entitiesToDtoList(userMapper.queryUserByIdList(userIdList));
    }

    /**
     * 菜单权限
     * 
     * @param roleId
     * @return
     * @author -- lijiangtao 2020年6月11日 下午5:22:13
     */
    private List<PermissionDTO> queryMenuPermission(String roleId) {
        IamRelationshipSqlBuilder sqlBuilder = new IamRelationshipSqlBuilder();
        sqlBuilder.andEntity1CodeEqualTo(roleId).andRelaCodeEqualTo(RelaCodeEnum.ROLE_MENU_PERM.getCode());
        List<String> permissionIdList = relationshipDao.selectListBySqlBuilder(sqlBuilder).stream().map(IamRelationship::getEntity2Code).collect(Collectors.toList());
        if (permissionIdList.isEmpty()) {
            return null;
        }
        return PermissionUtil.listToTree(PermissionConvert.INSTANCE.entitiesToDtoList(permissionMapper.queryPerission(permissionIdList)));
    }

    /**
     * 数据权限
     * 
     * @param roleId
     * @return
     * @author -- lijiangtao 2020年7月28日 上午9:38:37
     */
    private List<OrganDTO> queryDataPermission(String roleId) {
        IamRelationshipSqlBuilder sqlBuilder = new IamRelationshipSqlBuilder();
        sqlBuilder.andEntity1CodeEqualTo(roleId).andRelaCodeEqualTo(RelaCodeEnum.ROLE_DATA_PERM.getCode());
        List<String> permissionIdList = relationshipDao.selectListBySqlBuilder(sqlBuilder).stream().map(IamRelationship::getEntity2Code).collect(Collectors.toList());
        if (permissionIdList.isEmpty()) {
            return null;
        }
        return ForestNodeMerger.merge(OrganConvert.INSTANCE.entitiesToDTOList(permissionMapper.queryDataPermByList(new DataPermParam(permissionIdList))));
    }

    /**
     * 接口权限
     * 
     * @param roleId
     * @return
     * @author -- lijiangtao 2020年7月28日 上午9:41:04
     */
    private List<PermissionDTO> queryAPIPermission(String roleId) {
        IamRelationshipSqlBuilder sqlBuilder = new IamRelationshipSqlBuilder();
        sqlBuilder.andEntity1CodeEqualTo(roleId).andRelaCodeEqualTo(RelaCodeEnum.ROLE_API_PERM.getCode());
        List<String> permissionIdList = relationshipDao.selectListBySqlBuilder(sqlBuilder).stream().map(IamRelationship::getEntity2Code).collect(Collectors.toList());
        if (permissionIdList.isEmpty()) {
            return null;
        }
        return PermissionUtil.listToTree(PermissionConvert.INSTANCE.entitiesToDtoList(permissionMapper.queryPerission(permissionIdList)));
    }

    /**
     * 分页查询角色信息
     * 
     * @param roleDTO
     * @param pageable
     * @return
     * @author -- lijiangtao 2020年7月27日 下午3:50:27
     */
    @Override
    @SuppressWarnings("all")
    public Page<RoleDTO> queryRole(RoleDTO roleDTO, Pageable pageable) {
        //查询该用户的机构
        Map<String, String> mapType = iamRelationshipMapper.selectOrginIdByuserCode(roleDTO.getLoginCode());
        if (orginGrade.equals(mapType.get("type"))) {
            //一级机构
            IamRoleSqlBuilder sqlBuilder = this.setSqlBuilder(roleDTO, pageable);
            return new PageImpl(RoleConvert.INSTANCE.entitiesToDtoList(roleDao.selectListBySqlBuilder(sqlBuilder)), pageable, roleDao.countBySqlBuilder(sqlBuilder));
        }
        //二级机构
        List<IamRole> roleList = iamRoleMapper.getListRoleByUserCode(roleDTO.getLoginCode());
        Long roleCount = iamRoleMapper.getCountRoleByUserCode(roleDTO.getLoginCode());
        Page<RoleDTO> page = new PageImpl(RoleConvert.INSTANCE.entitiesToDtoList(roleList), pageable, roleCount);
        return page;
    }

    /**
     * setSqlBuilder
     * 
     * @param roleDTO
     * @param pageable
     * @return
     * @author -- lijiangtao 2020年7月18日 下午3:35:47
     */
    private IamRoleSqlBuilder setSqlBuilder(RoleDTO roleDTO, Pageable pageable) {
        if (StringUtils.isEmpty(roleDTO.getTenantCode())) {
            throw new ServiceException("tenantCode:租户代码不能为空");
        }
        if (StringUtils.isEmpty(roleDTO.getLoginCode())) {
            throw new ServiceException("登录账号不能为空");
        }
        IamRoleSqlBuilder sqlBuilder = new IamRoleSqlBuilder();
        sqlBuilder.setPageSize(pageable.getPageSize());
        sqlBuilder.setIndexNo((int) pageable.getOffset());
        if (!Objects.deepEquals(roleDTO.getTenantCode(), Const.ROOT_TENANT_CODE) || !Objects.deepEquals(roleDTO.getLoginCode(), Const.ROOT_USER_CODE)) {
            sqlBuilder.andTenantCodeEqualTo(roleDTO.getTenantCode());
        }
        if (StringUtils.isNotBlank(roleDTO.getRoleName())) {
            sqlBuilder.andRoleNameLikeBoth(roleDTO.getRoleName());
        }
        if (StringUtils.isNotBlank(roleDTO.getRoleAlias())) {
            sqlBuilder.andRoleAliasLikeBoth(roleDTO.getRoleAlias());
        }
        sqlBuilder.andIsDeletedEqualTo(YesOrNoEnum.NO.getCode()).andStateEqualTo(YesOrNoEnum.YES.getCode()).orderByUpdateTime(true).setAutoFilterNull(true);
        return sqlBuilder;
    }
}
